package qshell

import (
	"fmt"
	"log"
)

type Handle func(Context, []string)

type Shell struct {
	cmdMap    map[string]*Cmd
	inputChan chan *Record

	info    map[string]any
	now     *Record
	history []*Record

	isNode bool // 是否远程调用
}

// Record 写入记录
type Record struct {
	index    uint
	clientip string
	serverip string
	input    string
	out      string
}

// New Shell
func New() *Shell {
	return &Shell{
		inputChan: make(chan *Record),
		cmdMap:    make(map[string]*Cmd),
		info:      make(map[string]any),
	}
}

func Default() *Shell {
	shell := New()
	LoadMathShell(shell)
	return shell
}

// Cmd 增加cmd
func (s *Shell) Cmd(cmdStr string, handle Handle) *Cmd {
	if s.cmdMap[cmdStr] != nil {
		log.Fatalln(cmdStr, " rename")
	}
	cmd := &Cmd{
		handle: handle,
		next:   nil,
		Key:    cmdStr,
	}
	s.cmdMap[cmdStr] = cmd
	return cmd
}

// Listen 开启监听 shell 主流程
func (s *Shell) Listen() {
	go s.ListenCmd()
	s.ListenInput()
}

// ListenCmd 开启监听 shell 主流程
func (s *Shell) ListenCmd() {
	var index uint = 1
	for {
		fmt.Printf("%v> ", index)
		// 用户输入
		res := <-s.inputChan
		res.index = index
		s.now = res

		if s.isNode {
			// 远程调用
			s.Call(&index)
		} else { // 本地调用
			// 解析输入参数
			cmdStr, args, err := formatArgStr(res.input)
			if err != nil {
				continue
			}
			// 定位脚本编号
			cmdH := s.cmdMap[cmdStr]
			if cmdH == nil {
				continue
			}
			// 执行命令脚本
			cmdH.Do(&index, s, args)
		}
		// 结果有效
		if s.now.index != index {
			s.Out()
		}
	}
}
